﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace snacks
{
    class GameManager
    {
        public event Action Update;
        public bool IsGameEnded { get; set; }
        public Random Random => random;
        public readonly int N1, N2, M, K;    //N = map, M = snake, K = snacks
        // public readonly int SW, SH;

        int totSnack = 0;
        int maxSnack;
        Random random;
        Map map;
        PrintManager printManager;
        List<Snake> snakes = new List<Snake>();
        Snake hostSnake;
        int delay;
        bool hasHuman;

        public GameManager(int n1, int n2, int m, int k, int mxk,
            int delay, bool hasHuman) // n for mapsize, m for snakes,
            //k for snack, mxk max snacks, bufferWidth, bufferHeight
        {
            N1 = n1; N2 = n2; M = m; K = k; maxSnack = mxk;
            // SW = sW; SH = sH;
            this.delay = delay;
            this.hasHuman = hasHuman;

            // random = new Random((int)DateTime.Now.Ticks);
            random = new Random(233333333);
            map = new Map(N1, N2);
            printManager = new PrintManager(this, map);

            Console.CancelKeyPress += Stop;
        }

        public void Begin()
        {
            hostSnake = new Snake(this, map, new Vector(5, 5),
            hasHuman, 5, ConsoleColor.White);
            snakes.Add(hostSnake);

            for (int i = 0; i < M; ++i) snakes.Add(
                new Snake(this, map, new Vector(random.Next(1, N1 - 1), random.Next(1, N2 - 1)),
                    false, random.Next(3, 10), (ConsoleColor)random.Next(1, 15)));

            map.Update();
            printManager.Update();
        }

        public void frameUpdate()
        {
            /*            foreach(Snake s in snakes)
                        {
                            if (s.IsDead)
                            {
                                if (s == hostSnake) Stop();
                                else
                                {
                                    //s = new Snake()
                                    snakes.Remove(s);
                                }
                            } 
                        }*/ 

            //Console.

            //if (hostSnake.IsDead)Stop();
            snakes.RemoveAll(x => x.IsDead);
            if(Update != null)
                Update();
            // if (hostSnake.IsDead) hostSnake = snakes.Count == 0 ? 
            //     null : snakes[0];false
            
            // if (snakes.Count == 1) {
            //     // Console.Write("chanttoyuuteyo!");
            // }
            if (hostSnake == null || hostSnake.IsDead) {
                if (snakes.Count != 0) {
                    hostSnake = snakes[0];
                    if(hasHuman) hostSnake.controller = new ConsoleController(hostSnake);
                } else hostSnake = null;
            }

            if (Random.Next(0, 100) <= 2)  snakes.Add(
                new Snake(this, map, new Vector(random.Next(1, N1 - 1), random.Next(1, N2 - 1)),
                    false, random.Next(3, 20), (ConsoleColor)random.Next(1, 15)));

            Vector tmp;
            int k = random.Next(0, K) / 10;
            if (totSnack + k > maxSnack) k = maxSnack - totSnack;
            for (int i = 0; i < k; ++i)
            {
                tmp = new Vector(random.Next(1, N1 - 1), random.Next(1, N2 - 1));
                if (map[tmp].Type == BType.None)
                {
                    ++totSnack;
                    map[tmp] = new BSnackInfo(val: random.Next(1, 4));
                }
            }

            map.Update();
            printManager.Update();
        }
        public void Loop()
        {
            while (!IsGameEnded)
            {
                Task d = Task.Delay(delay);
                frameUpdate();
                d.Wait();
                //Thread.Sleep(delay);
            }
        }

        public void Stop(object s = null, ConsoleCancelEventArgs e = null)
        {
            IsGameEnded = true;
            Console.WriteLine("You're Dead.");
        }

        public Vector GetViewPos()
        {
            return hostSnake == null ? new Vector(0, 0) : hostSnake.HeadPos;
        }
    }
}
